﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Fast.Framework.Interfaces;


namespace Fast.Framework
{
    /// <summary>
    /// 动态条件表达式
    /// </summary>
    public static class DynamicWhereExpression
    {

        /// <summary>
        /// 创建动态条件表达式
        /// </summary>
        /// <typeparam name="T"></typeparam
        /// <returns></returns>
        public static DynamicWhereExpression<T> Create<T>() where T : class, new()
        {
            return new DynamicWhereExpression<T>();
        }

    }

    /// <summary>
    /// 动态条件表达式
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class DynamicWhereExpression<T> where T : class
    {

        /// <summary>
        /// And表达式
        /// </summary>
        private readonly List<Expression> AndExpressions;

        /// <summary>
        /// OR表达式
        /// </summary>
        private readonly List<Expression> OrExpressions;

        /// <summary>
        /// 构造方法
        /// </summary>
        public DynamicWhereExpression()
        {
            AndExpressions = new List<Expression>();
            OrExpressions = new List<Expression>();
        }

        /// <summary>
        /// 和
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns></returns>
        public DynamicWhereExpression<T> And(Expression<Func<T, bool>> expression)
        {
            AndExpressions.Add(expression.Body);
            return this;
        }

        /// <summary>
        /// 或
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns></returns>
        public DynamicWhereExpression<T> Or(Expression<Func<T, bool>> expression)
        {
            OrExpressions.Add(expression.Body);
            return this;
        }

        /// <summary>
        /// 和如果
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="expression">表达式</param>
        /// <returns></returns>
        public DynamicWhereExpression<T> AndIF(bool where, Expression<Func<T, bool>> expression)
        {
            if (where)
            {
                AndExpressions.Add(expression.Body);
            }
            return this;
        }

        /// <summary>
        /// 和如果
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="expression">表达式</param>
        /// <returns></returns>
        public DynamicWhereExpression<T> AndNotNull(object value, Expression<Func<T, bool>> expression)
        {
            if (value != null)
            {
                AndExpressions.Add(expression.Body);
            }
            return this;
        }

        /// <summary>
        /// 或如果
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="expression">表达式</param>
        /// <returns></returns>
        public DynamicWhereExpression<T> OrIF(bool where, Expression<Func<T, bool>> expression)
        {
            if (where)
            {
                OrExpressions.Add(expression.Body);
            }
            return this;
        }

        /// <summary>
        /// 构建
        /// </summary>
        /// <returns></returns>
        public Expression<Func<T, bool>> Build()
        {
            Expression bodyExpression = null;
            foreach (var ex in AndExpressions)
            {
                if (bodyExpression == null)
                {
                    bodyExpression = ex;
                }
                else
                {
                    bodyExpression = Expression.AndAlso(bodyExpression, ex);//拼接
                }
            }
            foreach (var ex in OrExpressions)
            {
                if (bodyExpression == null)
                {
                    bodyExpression = ex;
                }
                else
                {
                    bodyExpression = Expression.OrElse(bodyExpression, ex);//拼接
                }
            }
            if (bodyExpression == null)
            {
                bodyExpression = Expression.Constant(true);
            }
            var expression = (Expression<Func<T, bool>>)Expression.Lambda(bodyExpression, Expression.Parameter(typeof(T)));
            return expression;
        }
    }
}
